تعلم كيفية تصميم وبناء أنظمة OLAP ومستودعات بيانات قوية باستخدام بايثون. يغطي هذا الدليل كل شيء بدءًا من نمذجة البيانات وعمليات ETL إلى اختيار الأدوات المناسبة مثل Pandas و Dask و DuckDB.
مستودعات بيانات بايثون: دليل شامل لتصميم أنظمة المعالجة التحليلية الفورية (OLAP)
في عالم اليوم القائم على البيانات، لم تعد القدرة على تحليل كميات هائلة من المعلومات بسرعة مجرد ميزة تنافسية؛ بل أصبحت ضرورة. تعتمد الشركات في جميع أنحاء العالم على تحليلات قوية لفهم اتجاهات السوق، وتحسين العمليات، واتخاذ القرارات الاستراتيجية. وفي قلب هذه القدرة التحليلية يكمن مفهومان أساسيان: مستودع البيانات (DWH) وأنظمة المعالجة التحليلية الفورية (OLAP).
تقليديًا، كان بناء هذه الأنظمة يتطلب برامج متخصصة، غالبًا ما تكون مملوكة ومكلفة. ومع ذلك، أدى ظهور التقنيات مفتوحة المصدر إلى إضفاء الطابع الديمقراطي على هندسة البيانات. وتقود هذا التوجه لغة بايثون، وهي لغة متعددة الاستخدامات وقوية تتمتع بنظام بيئي غني يجعلها خيارًا استثنائيًا لبناء حلول بيانات متكاملة. يقدم هذا الدليل شرحًا شاملاً لتصميم وتنفيذ أنظمة تخزين البيانات و OLAP باستخدام حزمة بايثون، وهو مصمم لجمهور عالمي من مهندسي البيانات والمهندسين المعماريين والمطورين.
الجزء الأول: ركائز ذكاء الأعمال - DWH و OLAP
قبل الغوص في كود بايثون، من الضروري فهم المبادئ المعمارية. من الأخطاء الشائعة محاولة إجراء التحليلات مباشرة على قواعد البيانات التشغيلية، مما قد يؤدي إلى ضعف الأداء ورؤى غير دقيقة. هذه هي المشكلة التي صُممت مستودعات البيانات و OLAP لحلها.
ما هو مستودع البيانات (DWH)؟
مستودع البيانات هو مستودع مركزي يخزن البيانات المتكاملة من مصدر واحد أو أكثر من المصادر المتباينة. والغرض الأساسي منه هو دعم أنشطة ذكاء الأعمال (BI)، لا سيما التحليلات وإعداد التقارير. فكر فيه على أنه المصدر الوحيد للحقيقة للبيانات التاريخية للمؤسسة.
إنه يتناقض بشكل صارخ مع قاعدة بيانات المعالجة الفورية للمعاملات (OLTP)، التي تشغل التطبيقات اليومية (على سبيل المثال، نظام الدفع في التجارة الإلكترونية أو سجل معاملات البنك). إليك مقارنة سريعة:
- حجم العمل: تتعامل أنظمة OLTP مع عدد كبير من المعاملات الصغيرة والسريعة (قراءة، إدراج، تحديث). بينما تم تحسين مستودعات البيانات لعدد أقل من الاستعلامات المعقدة وطويلة الأمد التي تمسح ملايين السجلات (قراءة مكثفة).
- هيكل البيانات: تكون قواعد بيانات OLTP عالية التسوية (highly normalized) لضمان سلامة البيانات وتجنب التكرار. غالبًا ما تكون مستودعات البيانات غير مسواة (denormalized) لتبسيط وتسريع الاستعلامات التحليلية.
- الغرض: OLTP مخصص لتشغيل الأعمال. أما DWH فهو لتحليل الأعمال.
يتميز مستودع البيانات المصمم جيدًا بأربع خصائص رئيسية، غالبًا ما تُنسب إلى الرائد بيل إينمون:
- موجه حسب الموضوع: يتم تنظيم البيانات حول الموضوعات الرئيسية للعمل، مثل 'العميل' أو 'المنتج' أو 'المبيعات'، بدلاً من عمليات التطبيق.
- متكامل: يتم جمع البيانات من مصادر مختلفة ودمجها في تنسيق متسق. على سبيل المثال، قد يتم توحيد 'USA' و 'United States' و 'U.S.' جميعها إلى إدخال واحد 'United States'.
- متغير زمنيًا: تمثل البيانات في المستودع معلومات على مدى فترة زمنية طويلة (على سبيل المثال، 5-10 سنوات)، مما يسمح بالتحليل التاريخي وتحديد الاتجاهات.
- غير متطاير: بمجرد تحميل البيانات في المستودع، نادرًا ما يتم تحديثها أو حذفها، إن حدث ذلك. تصبح سجلاً دائمًا للأحداث التاريخية.
ما هي المعالجة التحليلية الفورية (OLAP)؟
إذا كان مستودع البيانات هو مكتبة البيانات التاريخية، فإن OLAP هو محرك البحث القوي والأداة التحليلية التي تتيح لك استكشافه. OLAP هي فئة من تكنولوجيا البرمجيات تمكن المستخدمين من تحليل المعلومات التي تم تلخيصها بسرعة في عروض متعددة الأبعاد، تُعرف باسم مكعبات OLAP.
مكعب OLAP هو القلب المفاهيمي لـ OLAP. ليس بالضرورة بنية بيانات مادية ولكنه طريقة لنمذجة البيانات وتصورها. يتكون المكعب من:
- المقاييس: هي نقاط البيانات الكمية الرقمية التي تريد تحليلها، مثل 'الإيرادات' أو 'الكمية المباعة' أو 'الربح'.
- الأبعاد: هي السمات الفئوية التي تصف المقاييس، وتوفر السياق. تشمل الأبعاد الشائعة 'الزمن' (سنة، ربع، شهر)، و'الجغرافيا' (دولة، منطقة، مدينة)، و'المنتج' (فئة، علامة تجارية، SKU).
تخيل مكعبًا من بيانات المبيعات. يمكنك النظر إلى إجمالي الإيرادات (المقياس) عبر أبعاد مختلفة. باستخدام OLAP، يمكنك إجراء عمليات قوية على هذا المكعب بسرعة لا تصدق:
- تقطيع (Slice): تقليل أبعاد المكعب عن طريق تحديد قيمة واحدة لبعد واحد. مثال: عرض بيانات المبيعات فقط لـ 'الربع الرابع 2023'.
- نرد (Dice): تحديد مكعب فرعي عن طريق تحديد نطاق من القيم لأبعاد متعددة. مثال: عرض مبيعات 'الإلكترونيات' و 'الملابس' (بعد المنتج) في 'أوروبا' و 'آسيا' (بعد الجغرافيا).
- تفصيل / تجميع (Drill-Down / Drill-Up): التنقل عبر مستويات التفاصيل داخل البعد. ينتقل التفصيل من الملخصات عالية المستوى إلى التفاصيل منخفضة المستوى (على سبيل المثال، من 'سنة' إلى 'ربع' إلى 'شهر'). التجميع (أو roll up) هو العكس.
- محور (Pivot): تدوير محاور المكعب للحصول على عرض جديد للبيانات. مثال: تبديل محوري 'المنتج' و 'الجغرافيا' لمعرفة المناطق التي تشتري أي منتجات، بدلاً من معرفة المنتجات التي تباع في أي مناطق.
أنواع أنظمة OLAP
هناك ثلاثة نماذج معمارية رئيسية لأنظمة OLAP:
- MOLAP (Multidimensional OLAP): هذا هو نموذج المكعب "الكلاسيكي". يتم استخراج البيانات من مستودع البيانات وتجميعها مسبقًا في قاعدة بيانات متعددة الأبعاد خاصة. المزايا: أداء استعلام سريع للغاية لأن جميع الإجابات محسوبة مسبقًا. العيوب: يمكن أن يؤدي إلى "انفجار البيانات" حيث يمكن أن يصبح عدد الخلايا المجمعة مسبقًا هائلاً، ويمكن أن يكون أقل مرونة إذا كنت بحاجة إلى طرح سؤال لم يكن متوقعًا.
- ROLAP (Relational OLAP): يحافظ هذا النموذج على البيانات في قاعدة بيانات علائقية (عادةً مستودع البيانات نفسه) ويستخدم طبقة بيانات وصفية متطورة لترجمة استعلامات OLAP إلى SQL قياسي. المزايا: قابلية عالية للتوسع، حيث يستفيد من قوة قواعد البيانات العلائقية الحديثة، ويمكنه الاستعلام عن بيانات أكثر تفصيلاً وفي الوقت الفعلي. العيوب: يمكن أن يكون أداء الاستعلام أبطأ من MOLAP حيث يتم إجراء التجميعات بشكل فوري.
- HOLAP (Hybrid OLAP): يحاول هذا النهج الجمع بين أفضل ما في العالمين. يخزن البيانات المجمعة عالية المستوى في مكعب بأسلوب MOLAP للسرعة ويحتفظ بالبيانات التفصيلية في قاعدة البيانات العلائقية ROLAP لتحليل التفاصيل.
بالنسبة لحزم البيانات الحديثة المبنية باستخدام بايثون، أصبحت الخطوط غير واضحة. مع ظهور قواعد البيانات العمودية السريعة بشكل لا يصدق، أصبح نموذج ROLAP هو السائد والفعال للغاية، وغالبًا ما يقدم أداءً يضاهي أنظمة MOLAP التقليدية دون صلابتها.
الجزء الثاني: النظام البيئي لبايثون لتخزين البيانات
لماذا تختار بايثون لمهمة سيطرت عليها تقليديًا منصات ذكاء الأعمال المؤسسية؟ تكمن الإجابة في مرونتها ونظامها البيئي القوي وقدرتها على توحيد دورة حياة البيانات بأكملها.
لماذا بايثون؟
- لغة موحدة: يمكنك استخدام بايثون لاستخراج البيانات (ETL)، وتحويلها، وتحميلها، وتنسيقها، وتحليلها، والتعلم الآلي، وتطوير واجهات برمجة التطبيقات. هذا يقلل من التعقيد والحاجة إلى تبديل السياق بين اللغات والأدوات المختلفة.
- نظام بيئي واسع من المكتبات: تمتلك بايثون مكتبات ناضجة ومختبرة لكل خطوة من العملية، من معالجة البيانات (Pandas, Dask) إلى التفاعل مع قواعد البيانات (SQLAlchemy) وإدارة سير العمل (Airflow, Prefect).
- مستقل عن الموردين: بايثون مفتوح المصدر ويتصل بكل شيء. سواء كانت بياناتك موجودة في قاعدة بيانات PostgreSQL، أو مستودع Snowflake، أو بحيرة بيانات S3، أو ورقة Google Sheet، فهناك مكتبة بايثون للوصول إليها.
- قابلية التوسع: يمكن أن تتوسع حلول بايثون من برنامج نصي بسيط يعمل على جهاز كمبيوتر محمول إلى نظام موزع يعالج بيتابايت من البيانات على مجموعة سحابية باستخدام أدوات مثل Dask أو Spark (عبر PySpark).
مكتبات بايثون الأساسية لحزمة مستودع البيانات
حل تخزين البيانات المعتمد على بايثون عادةً ليس منتجًا واحدًا بل مجموعة منسقة من المكتبات القوية. إليك الأساسيات:
لعمليات ETL/ELT (استخراج، تحويل، تحميل)
- Pandas: المعيار الفعلي لمعالجة البيانات في الذاكرة في بايثون. مثالي للتعامل مع مجموعات البيانات الصغيرة إلى المتوسطة (حتى بضعة غيغابايت). كائن DataFrame الخاص به بديهي وقوي لتنظيف البيانات وتحويلها وتحليلها.
- Dask: مكتبة حوسبة متوازية تتوسع بتحليلات بايثون الخاصة بك. توفر Dask كائن DataFrame موازيًا يحاكي واجهة برمجة تطبيقات Pandas ولكنه يمكن أن يعمل على مجموعات بيانات أكبر من الذاكرة عن طريق تقسيمها إلى أجزاء ومعالجتها بالتوازي عبر أنوية أو أجهزة متعددة.
- SQLAlchemy: مجموعة أدوات SQL الأولى و Object Relational Mapper (ORM) لبايثون. توفر واجهة برمجة تطبيقات متسقة وعالية المستوى للاتصال بأي قاعدة بيانات SQL تقريبًا، من SQLite إلى مستودعات البيانات المؤسسية مثل BigQuery أو Redshift.
- منسقات سير العمل (Airflow, Prefect, Dagster): لا يتم بناء مستودع البيانات على برنامج نصي واحد. إنه سلسلة من المهام المترابطة (استخراج من A، تحويل B، تحميل إلى C، فحص D). تسمح لك المنسقات بتعريف مهام سير العمل هذه على أنها رسوم بيانية موجهة غير دورية (DAGs)، وجدولتها، ومراقبتها، وإعادة محاولتها بقوة.
لتخزين البيانات ومعالجتها
- موصلات مستودعات البيانات السحابية: تسمح مكتبات مثل
snowflake-connector-pythonوgoogle-cloud-bigqueryوpsycopg2(لـ Redshift و PostgreSQL) بالتفاعل السلس مع مستودعات البيانات السحابية الرئيسية. - PyArrow: مكتبة حاسمة للعمل مع تنسيقات البيانات العمودية. توفر تنسيقًا موحدًا في الذاكرة وتتيح نقل البيانات عالي السرعة بين الأنظمة. إنها المحرك وراء التفاعلات الفعالة مع تنسيقات مثل Parquet.
- مكتبات Lakehouse الحديثة: للإعدادات المتقدمة، تسمح مكتبات مثل
deltalakeوpy-iceberg- ولمستخدمي Spark - الدعم الأصلي لـ PySpark لهذه التنسيقات لبايثون ببناء بحيرات بيانات موثوقة ومعاملاتية تعمل كأساس لمستودع.
الجزء الثالث: تصميم نظام OLAP باستخدام بايثون
الآن، دعنا ننتقل من النظرية إلى التطبيق. إليك دليل خطوة بخطوة لتصميم نظامك التحليلي.
الخطوة 1: نمذجة البيانات للتحليلات
أساس أي نظام OLAP جيد هو نموذج بياناته. الهدف هو هيكلة البيانات للاستعلام السريع والبديهي. النماذج الأكثر شيوعًا وفعالية هي المخطط النجمي ومتغيره، مخطط ندفة الثلج.
المخطط النجمي مقابل مخطط ندفة الثلج
المخطط النجمي هو الهيكل الأكثر استخدامًا لمستودعات البيانات. يتكون من:
- جدول حقائق مركزي: يحتوي على المقاييس (الأرقام التي تريد تحليلها) ومفاتيح أجنبية لجداول الأبعاد.
- عدة جداول أبعاد: يتم ربط كل جدول أبعاد بجدول الحقائق بمفتاح واحد ويحتوي على سمات وصفية. هذه الجداول غير مسواة إلى حد كبير من أجل البساطة والسرعة.
مثال: جدول `FactSales` بأعمدة مثل `DateKey` و `ProductKey` و `StoreKey` و `QuantitySold` و `TotalRevenue`. سيكون محاطًا بجداول `DimDate` و `DimProduct` و `DimStore`.
مخطط ندفة الثلج هو امتداد للمخطط النجمي حيث يتم تسوية جداول الأبعاد إلى جداول متعددة ذات صلة. على سبيل المثال، قد يتم تقسيم جدول `DimProduct` إلى جداول `DimProduct` و `DimBrand` و `DimCategory`.
توصية: ابدأ بـ المخطط النجمي. الاستعلامات أبسط (عدد أقل من الصلات)، وقواعد البيانات العمودية الحديثة فعالة جدًا في التعامل مع الجداول الواسعة وغير المسواة لدرجة أن فوائد التخزين لمخططات ندفة الثلج غالبًا ما تكون ضئيلة مقارنة بتكلفة الأداء للصلات الإضافية.
الخطوة 2: بناء خط أنابيب ETL/ELT في بايثون
عملية ETL هي العمود الفقري الذي يغذي مستودع البيانات الخاص بك. تتضمن استخراج البيانات من أنظمة المصدر، وتحويلها إلى تنسيق نظيف ومتسق، وتحميلها في نموذجك التحليلي.
دعونا نوضح ذلك باستخدام برنامج نصي بسيط في بايثون باستخدام Pandas. تخيل أن لدينا ملف CSV مصدر للطلبات الأولية.
# مثال مبسط لعملية ETL باستخدام بايثون و Pandas
import pandas as pd
# --- استخراج (EXTRACT) ---
print("استخراج بيانات الطلبات الأولية...")
source_df = pd.read_csv('raw_orders.csv')
# --- تحويل (TRANSFORM) ---
print("تحويل البيانات...")
# 1. تنظيف البيانات
source_df['order_date'] = pd.to_datetime(source_df['order_date'])
source_df['product_price'] = pd.to_numeric(source_df['product_price'], errors='coerce')
source_df.dropna(inplace=True)
# 2. إثراء البيانات - إنشاء بُعد تاريخ منفصل
dim_date = pd.DataFrame({
'DateKey': source_df['order_date'].dt.strftime('%Y%m%d').astype(int),
'Date': source_df['order_date'].dt.date,
'Year': source_df['order_date'].dt.year,
'Quarter': source_df['order_date'].dt.quarter,
'Month': source_df['order_date'].dt.month,
'DayOfWeek': source_df['order_date'].dt.day_name()
}).drop_duplicates().reset_index(drop=True)
# 3. إنشاء بُعد المنتج
dim_product = source_df[['product_id', 'product_name', 'category']].copy()
dim_product.rename(columns={'product_id': 'ProductKey'}, inplace=True)
dim_product.drop_duplicates(inplace=True).reset_index(drop=True)
# 4. إنشاء جدول الحقائق
fact_sales = source_df.merge(dim_date, left_on=source_df['order_date'].dt.date, right_on='Date')\
.merge(dim_product, left_on='product_id', right_on='ProductKey')
fact_sales = fact_sales[['DateKey', 'ProductKey', 'order_id', 'quantity', 'product_price']]
fact_sales['TotalRevenue'] = fact_sales['quantity'] * fact_sales['product_price']
fact_sales.rename(columns={'order_id': 'OrderCount'}, inplace=True)
# التجميع إلى المستوى المطلوب
fact_sales = fact_sales.groupby(['DateKey', 'ProductKey']).agg(
TotalRevenue=('TotalRevenue', 'sum'),
TotalQuantity=('quantity', 'sum')
).reset_index()
# --- تحميل (LOAD) ---
print("تحميل البيانات إلى التخزين المستهدف...")
# لهذا المثال، سنحفظ في ملفات Parquet، وهو تنسيق عمودي عالي الكفاءة
dim_date.to_parquet('warehouse/dim_date.parquet')
dim_product.to_parquet('warehouse/dim_product.parquet')
fact_sales.to_parquet('warehouse/fact_sales.parquet')
print("اكتملت عملية ETL!")
يوضح هذا البرنامج النصي البسيط المنطق الأساسي. في سيناريو واقعي، ستقوم بتغليف هذا المنطق في دوال وإدارة تنفيذه باستخدام منسق مثل Airflow.
الخطوة 3: اختيار وتنفيذ محرك OLAP
مع نمذجة بياناتك وتحميلها، تحتاج إلى محرك لأداء عمليات OLAP. في عالم بايثون، لديك العديد من الخيارات القوية، والتي تتبع في المقام الأول نهج ROLAP.
النهج أ: القوة الخفيفة - DuckDB
DuckDB هي قاعدة بيانات تحليلية مدمجة في العملية وهي سريعة بشكل لا يصدق وسهلة الاستخدام مع بايثون. يمكنها الاستعلام عن Pandas DataFrames أو ملفات Parquet مباشرة باستخدام SQL. إنها الخيار الأمثل لأنظمة OLAP الصغيرة إلى المتوسطة الحجم، والنماذج الأولية، والتطوير المحلي.
تعمل كمحرك ROLAP عالي الأداء. تكتب SQL قياسيًا، وتنفذه DuckDB بسرعة فائقة على ملفات البيانات الخاصة بك.
import duckdb
# الاتصال بقاعدة بيانات في الذاكرة أو ملف
con = duckdb.connect(database=':memory:', read_only=False)
# الاستعلام مباشرة عن ملفات Parquet التي أنشأناها سابقًا
# تفهم DuckDB المخطط تلقائيًا
result = con.execute("""
SELECT
p.category,
d.Year,
SUM(f.TotalRevenue) AS AnnualRevenue
FROM 'warehouse/fact_sales.parquet' AS f
JOIN 'warehouse/dim_product.parquet' AS p ON f.ProductKey = p.ProductKey
JOIN 'warehouse/dim_date.parquet' AS d ON f.DateKey = d.DateKey
WHERE p.category = 'Electronics'
GROUP BY p.category, d.Year
ORDER BY d.Year;
""").fetchdf() # fetchdf() يعيد Pandas DataFrame
print(result)
النهج ب: عمالقة النطاق السحابي - Snowflake, BigQuery, Redshift
بالنسبة للأنظمة المؤسسية واسعة النطاق، يعد مستودع البيانات السحابي هو الخيار القياسي. تتكامل بايثون بسلاسة مع هذه المنصات. ستقوم عملية ETL الخاصة بك بتحميل البيانات إلى مستودع البيانات السحابي، وسيقوم تطبيق بايثون الخاص بك (على سبيل المثال، لوحة معلومات ذكاء الأعمال أو دفتر Jupyter) بالاستعلام عنها.
يظل المنطق كما هو مع DuckDB، لكن الاتصال والنطاق مختلفان.
import snowflake.connector
# مثال على الاتصال بـ Snowflake وتشغيل استعلام
conn = snowflake.connector.connect(
user='your_user',
password='your_password',
account='your_account_identifier'
)
cursor = conn.cursor()
try:
cursor.execute("USE WAREHOUSE MY_WH;")
cursor.execute("USE DATABASE MY_DB;")
cursor.execute("""
SELECT category, YEAR(date), SUM(total_revenue)
FROM fact_sales
JOIN dim_product ON ...
JOIN dim_date ON ...
GROUP BY 1, 2;
""")
# جلب النتائج حسب الحاجة
for row in cursor:
print(row)
finally:
cursor.close()
conn.close()
النهج ج: متخصصو الوقت الفعلي - Apache Druid أو ClickHouse
لحالات الاستخدام التي تتطلب زمن استجابة استعلام أقل من الثانية على مجموعات بيانات ضخمة ومتدفقة (مثل تحليلات المستخدم في الوقت الفعلي)، تعد قواعد البيانات المتخصصة مثل Druid أو ClickHouse خيارات ممتازة. إنها قواعد بيانات عمودية مصممة لأحمال عمل OLAP. يتم استخدام بايثون لدفق البيانات إليها والاستعلام عنها عبر مكتبات العملاء الخاصة بها أو واجهات برمجة تطبيقات HTTP.
الجزء الرابع: مثال عملي - بناء نظام OLAP صغير
دعنا نجمع هذه المفاهيم في مشروع صغير: لوحة معلومات مبيعات تفاعلية. يوضح هذا نظام OLAP كامل، وإن كان مبسطًا، يعتمد على بايثون.
حزمتنا التقنية:
- ETL: بايثون و Pandas
- تخزين البيانات: ملفات Parquet
- محرك OLAP: DuckDB
- لوحة المعلومات: Streamlit (مكتبة بايثون مفتوحة المصدر لإنشاء تطبيقات ويب تفاعلية وجميلة لعلوم البيانات)
أولاً، قم بتشغيل البرنامج النصي لـ ETL من الجزء الثالث لإنشاء ملفات Parquet في دليل `warehouse/`.
بعد ذلك، قم بإنشاء ملف تطبيق لوحة المعلومات، `app.py`:
# app.py - لوحة معلومات مبيعات تفاعلية بسيطة
import streamlit as st
import duckdb
import pandas as pd
import plotly.express as px
# --- إعدادات الصفحة ---
st.set_page_config(layout="wide", page_title="لوحة معلومات المبيعات العالمية")
st.title("لوحة معلومات OLAP تفاعلية للمبيعات")
# --- الاتصال بـ DuckDB ---
# سيقوم هذا بالاستعلام مباشرة عن ملفات Parquet الخاصة بنا
con = duckdb.connect(database=':memory:', read_only=True)
# --- تحميل بيانات الأبعاد للمرشحات ---
@st.cache_data
def load_dimensions():
products = con.execute("SELECT DISTINCT category FROM 'warehouse/dim_product.parquet'").fetchdf()
years = con.execute("SELECT DISTINCT Year FROM 'warehouse/dim_date.parquet' ORDER BY Year").fetchdf()
return products['category'].tolist(), years['Year'].tolist()
categories, years = load_dimensions()
# --- الشريط الجانبي للمرشحات (تقطيع ونرد!) ---
st.sidebar.header("مرشحات OLAP")
selected_categories = st.sidebar.multiselect(
'حدد فئات المنتجات',
options=categories,
default=categories
)
selected_year = st.sidebar.selectbox(
'حدد السنة',
options=years,
index=len(years)-1 # الافتراضي هو أحدث سنة
)
# --- بناء استعلام OLAP ديناميكيًا ---
if not selected_categories:
st.warning("الرجاء تحديد فئة واحدة على الأقل.")
st.stop()
query = f"""
SELECT
d.Month,
d.MonthName, -- بافتراض وجود MonthName في DimDate
p.category,
SUM(f.TotalRevenue) AS Revenue
FROM 'warehouse/fact_sales.parquet' AS f
JOIN 'warehouse/dim_product.parquet' AS p ON f.ProductKey = p.ProductKey
JOIN 'warehouse/dim_date.parquet' AS d ON f.DateKey = d.DateKey
WHERE d.Year = {selected_year}
AND p.category IN ({str(selected_categories)[1:-1]})
GROUP BY d.Month, d.MonthName, p.category
ORDER BY d.Month;
"""
# --- تنفيذ الاستعلام وعرض النتائج ---
@st.cache_data
def run_query(_query):
return con.execute(_query).fetchdf()
results_df = run_query(query)
if results_df.empty:
st.info(f"لم يتم العثور على بيانات للمرشحات المحددة في عام {selected_year}.")
else:
# --- المرئيات الرئيسية للوحة المعلومات ---
col1, col2 = st.columns(2)
with col1:
st.subheader(f"الإيرادات الشهرية لعام {selected_year}")
fig = px.line(
results_df,
x='MonthName',
y='Revenue',
color='category',
title='الإيرادات الشهرية حسب الفئة'
)
st.plotly_chart(fig, use_container_width=True)
with col2:
st.subheader("الإيرادات حسب الفئة")
category_summary = results_df.groupby('category')['Revenue'].sum().reset_index()
fig_pie = px.pie(
category_summary,
names='category',
values='Revenue',
title='حصة الإيرادات الإجمالية حسب الفئة'
)
st.plotly_chart(fig_pie, use_container_width=True)
st.subheader("البيانات التفصيلية")
st.dataframe(results_df)
لتشغيل هذا، احفظ الكود باسم `app.py` ونفذ `streamlit run app.py` في الطرفية الخاصة بك. سيؤدي هذا إلى تشغيل متصفح ويب مع لوحة المعلومات التفاعلية الخاصة بك. تسمح المرشحات الموجودة في الشريط الجانبي للمستخدمين بأداء عمليات OLAP 'التقطيع' و 'النرد'، ويتم تحديث لوحة المعلومات في الوقت الفعلي عن طريق إعادة الاستعلام من DuckDB.
الجزء الخامس: مواضيع متقدمة وأفضل الممارسات
أثناء انتقالك من مشروع صغير إلى نظام إنتاجي، ضع في اعتبارك هذه المواضيع المتقدمة.
قابلية التوسع والأداء
- استخدم Dask لعمليات ETL الكبيرة: إذا تجاوزت بيانات المصدر ذاكرة الوصول العشوائي لجهازك، فاستبدل Pandas بـ Dask في برامج ETL النصية الخاصة بك. واجهة برمجة التطبيقات متشابهة جدًا، لكن Dask ستتعامل مع المعالجة خارج الذاكرة والمعالجة المتوازية.
- التخزين العمودي هو المفتاح: قم دائمًا بتخزين بيانات المستودع الخاص بك بتنسيق عمودي مثل Apache Parquet أو ORC. هذا يسرع بشكل كبير الاستعلامات التحليلية، التي عادة ما تحتاج فقط إلى قراءة بضعة أعمدة من جدول واسع.
- التقسيم: عند تخزين البيانات في بحيرة بيانات (مثل S3 أو نظام ملفات محلي)، قم بتقسيم بياناتك إلى مجلدات بناءً على بُعد يتم تصفيته بشكل متكرر، مثل التاريخ. على سبيل المثال: `warehouse/fact_sales/year=2023/month=12/`. هذا يسمح لمحركات الاستعلام بتخطي قراءة البيانات غير ذات الصلة، وهي عملية تُعرف باسم 'تقليم الأقسام'.
الطبقة الدلالية
مع نمو نظامك، ستجد أن منطق العمل (مثل تعريف 'المستخدم النشط' أو 'هامش الربح الإجمالي') يتكرر في استعلامات ولوحات معلومات متعددة. تحل الطبقة الدلالية هذه المشكلة من خلال توفير تعريف مركزي ومتسق لمقاييس وأبعاد عملك. أدوات مثل dbt (أداة بناء البيانات) استثنائية لهذا الغرض. على الرغم من أنها ليست أداة بايثون في حد ذاتها، إلا أن dbt تتكامل تمامًا مع سير عمل منسق بواسطة بايثون. يمكنك استخدام dbt لنمذجة المخطط النجمي وتحديد المقاييس، ثم يمكن استخدام بايثون لتنسيق عمليات dbt وإجراء تحليل متقدم على الجداول النظيفة الناتجة.
حوكمة البيانات وجودتها
المستودع جيد فقط بقدر جودة البيانات الموجودة فيه. قم بدمج فحوصات جودة البيانات مباشرة في خطوط أنابيب ETL الخاصة بك في بايثون. تتيح لك مكتبات مثل Great Expectations تحديد 'توقعات' حول بياناتك (على سبيل المثال، يجب ألا يكون `customer_id` فارغًا أبدًا، يجب أن يكون `revenue` بين 0 و 1,000,000). يمكن لوظيفة ETL الخاصة بك بعد ذلك أن تفشل أو تنبهك إذا كانت البيانات الواردة تنتهك هذه العقود، مما يمنع البيانات السيئة من إفساد المستودع الخاص بك.
الخلاصة: قوة النهج القائم على الكود أولاً
لقد غيرت بايثون بشكل أساسي مشهد تخزين البيانات وذكاء الأعمال. إنها توفر مجموعة أدوات مرنة وقوية ومحايدة للموردين لبناء أنظمة تحليلية متطورة من الألف إلى الياء. من خلال الجمع بين أفضل المكتبات في فئتها مثل Pandas و Dask و SQLAlchemy و DuckDB، يمكنك إنشاء نظام OLAP كامل قابل للتطوير والصيانة.
تبدأ الرحلة بفهم قوي لمبادئ نمذجة البيانات مثل المخطط النجمي. ومن هناك، يمكنك بناء خطوط أنابيب ETL قوية لتشكيل بياناتك، واختيار محرك الاستعلام المناسب لنطاقك، وحتى بناء تطبيقات تحليلية تفاعلية. هذا النهج القائم على الكود أولاً، والذي غالبًا ما يكون مبدأ أساسيًا في 'حزمة البيانات الحديثة'، يضع قوة التحليلات مباشرة في أيدي المطورين وفرق البيانات، مما يمكنهم من بناء أنظمة مصممة خصيصًا لتلبية احتياجات مؤسستهم.